package websocket

import (
	"errors"
	"src/connection"
	"src/global"
	"src/model"
	"src/model/ProtoModel"
	"src/service"
)

// subscribe 订阅逻辑
type WebSocketService struct {
}

func (this *WebSocketService) RoomOut(conn *connection.Ws) error {
	reply := &ProtoModel.ReplyBodyProto{
		Key:  "room_out",
		Code: "200",
		Data: make(map[string]string),
	}
	room := global.Ws_.GetRoomListVal(conn.RoomNo)
	if conn.RoomNo != "" && room != nil && room[conn.Id] == "" {

		global.Ws_.DelRoomList(conn.RoomNo, conn.Id)
		reply.Code = "200"
		reply.Data["msg"] = "您已退出房间"
		reply.Data["uid"] = conn.Uid

		(&service.ReplyBody{}).SendMsgToConn(reply, conn.Id)
		var messageProto ProtoModel.MessageProto
		messageProto.Action = "user_out_room"
		messageProto.Title = "房间消息"
		messageProto.Content = make(map[string]string)
		messageProto.Content["roomNo"] = conn.RoomNo
		messageProto.Content["uid"] = conn.Uid
		messageProto.Content["nickname"] = conn.Nickname
		messageProto.Content["avatar"] = conn.Avatar
		messageProto.Content["msg"] = conn.Nickname + "退出房间"
		(&service.Message{}).SendMsgToRoom(&messageProto, conn.RoomNo)
		conn.RoomNo = ""
	}
	return nil
}
func (this *WebSocketService) RoomBind(conn *connection.Ws, roomBind model.RoomBindModel) error {
	var err error
	reply := &ProtoModel.ReplyBodyProto{
		Key:  "room_bind",
		Code: "200",
		Data: make(map[string]string),
	}
	defer func() {
		if err != nil {
			//绑定失败返回前端
			//ret := bytes.Buffer{}
			//reply.Code = "401"
			reply.Data["msg"] = "绑定失败" + err.Error()
			//data, _ := proto.Marshal(reply)
			//ret.WriteByte(byte(ProtoModel.DataTypeProto_REPLY.Number()))
			//ret.Write(data)
			//conn.WriteMes(ret.Bytes())
			(&service.ReplyBody{}).SendMsgToConn(reply, conn.Id)
		}
	}()
	//ClientBindProto
	// 登录鉴权
	if roomBind.Token == "" {
		return errors.New("token不能存在")
	}
	auth := &service.Auth{}
	userinfo, err := auth.RoomBindAuthWs(&roomBind, conn)
	if err != nil {
		reply.Code = "401"
		return err
	}

	////删除未登录的记录
	//delete(global.Ws_.ConnList, conn.Id)
	reply.Code = "200"
	reply.Data["msg"] = userinfo.Nickname + "进入房间"
	reply.Data["uid"] = userinfo.Uid
	//data, _ := proto.Marshal(reply)
	//授权绑定成功 发送消息给用户
	//buf := bytes.NewBuffer([]byte{uint8(ProtoModel.DataTypeProto_REPLY.Number())})
	//buf.Write(data)
	//err = conn.WriteMes(buf.Bytes())
	//(&ReplyBody{}).Send(data, conn.Id)
	(&service.ReplyBody{}).SendMsgToConn(reply, conn.Id)
	var messageProto ProtoModel.MessageProto
	messageProto.Action = "user_in_room"
	messageProto.Title = "房间消息"
	messageProto.Content = make(map[string]string)
	messageProto.Content["roomNo"] = conn.RoomNo
	messageProto.Content["uid"] = conn.Uid
	messageProto.Content["nickname"] = conn.Nickname
	messageProto.Content["avatar"] = conn.Avatar
	messageProto.Content["msg"] = conn.Nickname + "进入房间"
	(&service.Message{}).SendMsgToRoom(&messageProto, conn.RoomNo)
	if err != nil {
		return err
	}
	return nil
}

// 对已经绑定过cid和uid的链接 绑定房间号
func (this *WebSocketService) BindRoom(userBind *model.RoomBindModel) error {

	reply := &ProtoModel.ReplyBodyProto{
		Key:  "room_bind",
		Code: "200",
		Data: make(map[string]string),
	}
	if userBind.RoomNo == "" {
		return errors.New("RoomNo 不能为空")
	}
	if userBind.Uid == "" {
		return errors.New("Uid 不能为空")
	}
	cons := global.Ws_.UserList[userBind.Uid]
	if cons != nil {
		var messageProto ProtoModel.MessageProto
		for _, connId := range cons {

			//connId := cons[0]
			conn := global.Ws_.ConnList[connId]
			oldRoomNo := conn.RoomNo
			//删除直接绑定过的房间号
			if oldRoomNo != "" {
				(service.AuthI).DelOldRoomBind(userBind.Uid, oldRoomNo)
			}
			global.Ws_.ConnList[connId].RoomNo = userBind.RoomNo
			room := global.Ws_.RoomList[userBind.RoomNo]
			//房间不存在，创建房间
			if room == nil {
				//a:=make(map[string]model.RoomBindModel)
				room = make(map[string]string)
				room[conn.Id] = conn.Uid
				//绑定房间用户数据
				global.Ws_.RoomList[userBind.RoomNo] = room
			} else {
				//绑定房间 用户数据
				room[conn.Id] = conn.Uid
				//绑定房间用户数据
				global.Ws_.RoomList[userBind.RoomNo] = room
			}
			(&service.ReplyBody{}).SendMsgToConn(reply, conn.Id)
			messageProto.Action = "user_in_room"
			messageProto.Title = "房间消息"
			messageProto.Content = make(map[string]string)
			messageProto.Content["roomNo"] = conn.RoomNo
			messageProto.Content["uid"] = conn.Uid
			messageProto.Content["nickname"] = conn.Nickname
			messageProto.Content["avatar"] = conn.Avatar
			messageProto.Content["msg"] = conn.Nickname + "进入房间"
			(&service.Message{}).SendMsgToRoom(&messageProto, conn.RoomNo)
		}
	}
	return nil
}

// 绑定用户uid 和链接的cid
func (this *WebSocketService) BindUser(userBind *model.UserBindProto) error {

	if len(userBind.Uid) < 1 {
		return errors.New("用户uid长度不能少于1位")

	}
	if len(userBind.Cid) < 1 {
		return errors.New("用户Cid长度不能少于1位")

	}
	conn := global.Ws_.ConnList[userBind.Cid]
	if conn == nil {
		return errors.New("用户链接已断开")
	}
	conn.User.AppVersion = userBind.AppVersion
	conn.User.Channel = userBind.Channel
	conn.User.DeviceName = userBind.DeviceName
	conn.User.DeviceId = userBind.DeviceId
	conn.User.OsVersion = userBind.OsVersion
	conn.User.Language = userBind.Language
	conn.Did = userBind.DeviceId
	//conn.User.
	//global.Ws_.ConnList[global.Inc().Id]=conn
	var uid = userBind.Uid
	conn.Uid = uid
	userConn := global.Ws_.UserList[uid]
	if userConn == nil {
		userConn = append(userConn[:], conn.Id)
	} else {
		var has = false
		for _, cid := range userConn {
			if cid == conn.Id {
				has = true
			}
		}
		//未绑定过 需要添加绑定，绑定过就忽略
		if has == false {
			userConn = append(userConn[:], conn.Id)
		}
	}
	global.Ws_.UserList[uid] = userConn
	global.Ws_.ConnList[conn.Id] = conn
	reply := &ProtoModel.ReplyBodyProto{
		Key:  "user_bind",
		Code: "200",
		Data: make(map[string]string),
	}
	(&service.ReplyBody{}).SendMsgToConn(reply, conn.Id)
	return nil
}
func (this *WebSocketService) ClientBindRoom(conn *connection.Ws, clientBind model.ClientBindProto) error {

	return nil
}
func (this *WebSocketService) ClientBind(conn *connection.Ws, clientBind model.ClientBindProto) error {
	var err error
	reply := &ProtoModel.ReplyBodyProto{
		Key:  "client_bind",
		Code: "200",
		Data: make(map[string]string),
	}
	defer func() {
		if err != nil {
			//绑定失败返回前端
			reply.Code = "401"
			reply.Data["msg"] = err.Error()
			//reply.Message=err.Error()
			(&service.ReplyBody{}).SendMsgToConn(reply, conn.Id)
			return
		}
	}()
	// 登录鉴权
	if clientBind.Token == "" {
		reply.Code = "201"
		reply.Message = "token不能存在"
		//授权绑定成功 发送消息给用户
		(&service.ReplyBody{}).SendMsgToConn(reply, conn.Id)
		return errors.New("token不能存在")
	}
	auth := &service.Auth{}
	userinfo, err := auth.Auth(clientBind.Token)
	if err != nil {
		reply.Code = "401"
		reply.Message = err.Error()
		//授权绑定成功 发送消息给用户
		return err
	}
	////仅限制一个设备在线
	//if config.V().GetBool("online.only-one-online") {
	//	wscon, err := auth.CheckUidDid(userinfo.Uid, clientBind.DeviceId)
	//	if err != nil {
	//		//设备冲突是否关闭的新链接
	//		if config.V().GetInt("conflict-close-type") == 1 {
	//			conn.Close()
	//			return err
	//		}
	//		wscon.Close()
	//		//return err
	//	}
	//} else {
	//	wscon, err := auth.CheckUidDid(userinfo.Uid, clientBind.DeviceId)
	//	if err != nil {
	//		//设备冲突是否关闭的新链接
	//		if config.V().GetInt("conflict-close-type") == 1 {
	//			conn.Close()
	//			return err
	//		}
	//		//关闭已在线的链接
	//		wscon.Close()
	//		//return err
	//	}
	//}
	//fmt.Println("jwtAuth(clientBind.Token) uid:", userinfo.Uid)
	//conn.Uid = new(string)
	//conn.Uid=userinfo.Uid
	conn.User.AppVersion = clientBind.AppVersion
	conn.User.Channel = clientBind.Channel
	conn.User.DeviceName = clientBind.DeviceName
	conn.User.DeviceId = clientBind.DeviceId
	conn.User.OsVersion = clientBind.OsVersion
	conn.User.Language = clientBind.Language
	conn.Did = clientBind.DeviceId
	//conn.User.
	//global.Ws_.ConnList[global.Inc().Id]=conn
	var uid = userinfo.Uid
	conn.Uid = uid
	conn.Nickname = userinfo.Nickname
	conn.Avatar = userinfo.Avatar
	user := global.Ws_.GetUserListVal(uid)
	global.Ws_.UpdateUserList(uid, append(user[:], conn.Id))
	global.Ws_.UpdateConnList(conn.Id, conn)

	reply.Code = "200"
	//授权绑定成功 发送消息给用户
	(&service.ReplyBody{}).SendMsgToConn(reply, conn.Id)
	return err
}
